package lv.solcraft.replication.server.tests.http;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.Date;
import java.util.zip.GZIPInputStream;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.io.IOUtils;
import org.restlet.Client;
import org.restlet.data.CharacterSet;
import org.restlet.data.Encoding;
import org.restlet.data.Language;
import org.restlet.data.MediaType;
import org.restlet.data.Protocol;
import org.restlet.data.Response;
import org.restlet.resource.StringRepresentation;

import com.noelios.restlet.application.EncodeRepresentation;
import com.noelios.restlet.util.Base64;

public class HttpTestIntegration {

    private static long totalSent = 0;
    private static long startTime = 0;
    private static final Client client = new Client(Protocol.HTTP);

    public static void main(String[] args) throws Exception {
        while (true) {
            execute(args);
            Thread.sleep(1000 * 60);
        }
    }

    private static void execute(String[] args) throws MalformedURLException, IOException, ProtocolException {
        long siteId = 1;
        final JSONArray opers = new JSONArray();
        for (int i = 0; i < 100; i++) {
            JSONObject oper = new JSONObject();
            JSONObject id = new JSONObject();
            id.put("originOperId", System.nanoTime());
            id.put("originSiteId", siteId);
            oper.put("id", id);
            JSONObject record = new JSONObject();
            record.put("table", "TABLE1");
            record.put("recordSiteId", i);
            record.put("recordId", System.nanoTime());
            oper.put("record", record);
            oper.put("type", "INSERT");
            JSONArray fields = new JSONArray();
            for (int j = 0; j < 5; j++) {
                JSONObject field = new JSONObject();
                field.put("name", "field" + j);
                field.put("value", "some value " + System.nanoTime());
                fields.add(field);
            }
            oper.put("fields", fields);
            JSONArray infoFields = new JSONArray();
            for (int j = 0; j < 1; j++) {
                JSONObject field = new JSONObject();
                field.put("name", "infoField" + j);
                field.put("value", "info " + System.nanoTime());
                fields.add(field);
            }
            oper.put("infoFields", infoFields);
            JSONArray blobFields = new JSONArray();
            for (int j = 0; j < 1; j++) {
                JSONObject field = new JSONObject();
                field.put("name", "blobField" + j);
                field.put("value", Base64.encode("test value".getBytes(), true));
                blobFields.add(field);
            }
            oper.put("blobFields", blobFields);
            opers.add(oper);
        }
        startTime = System.currentTimeMillis();
        System.out.println("START");
        for (int i = 0; i < 100; i++) {
            storeOpers(siteId, opers);
        }
        System.out.println("DONE! " + totalSent);
        //
        // start = System.currentTimeMillis();
        // System.out.println("START");
        // for (int i = 0; i < 10; i++) {
        // getOpers();
        // }
        // end = System.currentTimeMillis() - start;
        // System.out.println("DONE IN " + end / 1000 + "s");
    }

    private static void storeOpers(long siteId, JSONArray opers) throws MalformedURLException, IOException, ProtocolException {
        // System.out.println("START " + new Date());
        long id = System.nanoTime();
        for (Object obj : opers) {
            JSONObject json = (JSONObject) obj;
            json.getJSONObject("id").put("originOperId", id++);
        }
        // System.out.println(opers.getJSONObject(1).getJSONObject("id"));
        StringRepresentation stringRepresentation = new StringRepresentation(opers.toString(), MediaType.TEXT_PLAIN, Language.ALL, CharacterSet.UTF_8);
        Response response = client.post("http://localhost:8080/api/servers/server1/send/" + siteId, new EncodeRepresentation(Encoding.GZIP, stringRepresentation));
        assertTrue(response.getStatus().isSuccess());
        totalSent += opers.size();
        if (totalSent % 10000 == 0) {
            long opersPerSecond = totalSent / ((System.currentTimeMillis() - startTime) / 1000);
            System.out.println("Total " + totalSent + ", opers per sec " + opersPerSecond + ", " + new Date());
        }
    }

    private static void getOpers() throws MalformedURLException, IOException {
        URL url = new URL("http://localhost:8080/api/servers/server1/execute/2");
        HttpURLConnection con = (HttpURLConnection) url.openConnection();
        con.setRequestProperty("Accept-Encoding", "gzip, deflate");
        con.connect();
        assertEquals(200, con.getResponseCode());
        try {
            String string = IOUtils.toString(new GZIPInputStream(con.getInputStream()));
            JSONArray jsonArray = JSONArray.fromObject(string);
            System.out.println("Oper count: " + jsonArray.size());
        } finally {
            con.disconnect();
        }
    }
}
